package com.zuo_book.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zuo_book.common.BusinessException;
import com.zuo_book.common.ResultCode;
import com.zuo_book.dto.JwtTokenDTO;
import com.zuo_book.dto.UserLoginDTO;
import com.zuo_book.dto.UserRegisterDTO;
import com.zuo_book.entity.User;
import com.zuo_book.mapper.UserMapper;
import com.zuo_book.security.JwtUtils;
import com.zuo_book.service.AuthService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 认证服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AuthServiceImpl implements AuthService {

    private final UserMapper userMapper;
    private final AuthenticationManager authenticationManager;
    private final JwtUtils jwtUtils;
    private final PasswordEncoder passwordEncoder;

    @Override
    public JwtTokenDTO login(UserLoginDTO loginDTO) {
        try {
            log.info("开始用户认证: {}", loginDTO.getUsername());

            // 认证用户
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword())
            );

            // 存储认证信息
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 获取认证用户信息
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            log.info("用户认证成功: {}, 角色: {}", userDetails.getUsername(), userDetails.getAuthorities());

            // 生成JWT
            log.info("开始生成JWT令牌...");
            String token = jwtUtils.generateToken(userDetails);
            log.info("JWT令牌生成成功, 长度: {}", token.length());

            // 获取角色
            String role = userDetails.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.joining(","));

            // 查询用户
            User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                    .eq(User::getUsername, userDetails.getUsername()));

            if (user == null) {
                log.error("已认证的用户在数据库中未找到: {}", userDetails.getUsername());
                throw new BusinessException(ResultCode.USER_NOT_EXIST);
            }

            // 更新最后登录时间
            userMapper.updateLastLoginTime(user.getId());

            // 构建返回对象
            JwtTokenDTO tokenDTO = JwtTokenDTO.builder()
                    .token(token)
                    .tokenType("Bearer")
                    .userId(user.getId())
                    .username(user.getUsername())
                    .role(role)
                    .build();

            log.info("登录流程完成, 用户: {}, 令牌类型: {}", user.getUsername(), tokenDTO.getTokenType());

            return tokenDTO;
        } catch (BadCredentialsException e) {
            log.error("用户认证失败，密码错误: {}", loginDTO.getUsername());
            throw new BusinessException(ResultCode.PASSWORD_ERROR);
        } catch (Exception e) {
            log.error("登录过程发生错误: " + e.getMessage(), e);
            throw new BusinessException(ResultCode.FAILED, "登录失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(UserRegisterDTO registerDTO) {
        // 校验密码
        if (!Objects.equals(registerDTO.getPassword(), registerDTO.getConfirmPassword())) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED, "两次密码不一致");
        }
        // 验证用户名是否存在
        if (checkUsernameExists(registerDTO.getUsername())) {
            throw new BusinessException(ResultCode.USERNAME_EXISTS);
        }

        // 验证邮箱是否存在
        if (checkEmailExists(registerDTO.getEmail())) {
            throw new BusinessException(ResultCode.EMAIL_EXISTS);
        }

        // 创建用户
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);

        // 设置默认角色和状态
        user.setRole("ROLE_USER");
        user.setStatus(1); // 1-正常
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 设置默认头像
        if (user.getAvatar() == null || user.getAvatar().isEmpty()) {
            user.setAvatar("https://secure.gravatar.com/avatar/00000000000000000000000000000000?d=mp&f=y");
        }

        // 保存用户
        userMapper.insert(user);
    }

    @Override
    public boolean checkUsernameExists(String username) {
        return userMapper.selectCount(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)) > 0;
    }

    @Override
    public boolean checkEmailExists(String email) {
        return userMapper.selectCount(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, email)) > 0;
    }
}
